#include <arch/riscv64/mm/memmap.h>
#include <libs/klibc.h>
#include <drivers/kernel_logger.h>
#include <mm/mm.h>

// 内存类型名称映射
static const char* memmap_type_names[] = {
    "USABLE",
    "RESERVED", 
    "ACPI_RECLAIMABLE",
    "ACPI_NVS",
    "BAD_MEMORY",
    "BOOTLOADER_RECLAIMABLE",
    "EXECUTABLE_AND_MODULES",
    "FRAMEBUFFER"
};

// 获取内存类型名称
static const char* get_memmap_type_name(uint64_t type) {
    if (type < sizeof(memmap_type_names) / sizeof(memmap_type_names[0])) {
        return memmap_type_names[type];
    }
    return "UNKNOWN";
}

// 打印所有内存映射信息

void print_limine_memmap(void) {
    struct limine_memmap_response *memmap = memmap_request.response;
    if (!memmap) {
        printk("[MEMMAP] No memory map response available\n");
        return;
    }

    uint64_t hhdm_offset = get_physical_memory_offset();
    const uint64_t IDENTITY_LIMIT = 0x100000000ULL; /* 4 GiB */

    printk("[MEMMAP] Limine Memory Map (Total: %lu regions)\n", memmap->entry_count);
    printk("[MEMMAP] ==================================================\n");

    uint64_t total_usable = 0;
    uint64_t total_reserved = 0;
    uint64_t total_bootloader = 0;

    for (uint64_t i = 0; i < memmap->entry_count; i++) {
        struct limine_memmap_entry *entry = memmap->entries[i];
        const char *type_name = get_memmap_type_name(entry->type);

        uint64_t start = entry->base;
        uint64_t end = entry->base + entry->length;
        uint64_t size_mb = entry->length / (1024 * 1024);

        printk("[MEMMAP] Region %lu: 0x%016lx - 0x%016lx | len=%lu MiB (%lu bytes) ! %s\n",
                  i, start, end, size_mb, entry->length, type_name);

        /* 1) 恒等映射部分（low 4GiB） */
        if (start < IDENTITY_LIMIT) {
            uint64_t id_end = (end <= IDENTITY_LIMIT) ? end : IDENTITY_LIMIT;
            uint64_t id_len = id_end - start;
            printk("    Identity-mapped (PA==VA): 0x%016lx - 0x%016lx (len=%lu bytes)\n",
                      start, id_end, id_len);
        }

        /* 2) HHDM 映射部分（如果 hhdm_offset 非零，则把整个 region 都可以表示为 HHDM 映射） */
        if (hhdm_offset != 0) {
            /* 对于整段 region，我们总是可以计算 VA = PA + hhdm_offset */
            uint64_t va_start = start + hhdm_offset;
            uint64_t va_end   = end   + hhdm_offset;
            printk("    HHDM-mapped (VA = PA + HHDM):\n");
            printk("      VA Start = 0x%016lx\n", va_start);
            printk("      VA End   = 0x%016lx\n", va_end);
            printk("      Offset   = +0x%016lx (HHDM)\n", hhdm_offset);
        } else {
            /* 没有 HHDM 的情况下，如果也不在低 4GiB，则标注未映射 */
            if (start >= IDENTITY_LIMIT) {
                printk("    VA = <not mapped in HHDM or identity>\n");
            }
        }

        /* 统计不同类型的内存 */
        switch (entry->type) {
            case LIMINE_MEMMAP_USABLE:
                total_usable += entry->length;
                break;
            case LIMINE_MEMMAP_RESERVED:
            case LIMINE_MEMMAP_ACPI_RECLAIMABLE:
            case LIMINE_MEMMAP_ACPI_NVS:
            case LIMINE_MEMMAP_BAD_MEMORY:
                total_reserved += entry->length;
                break;
            case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE:
            case LIMINE_MEMMAP_KERNEL_AND_MODULES:
            case LIMINE_MEMMAP_FRAMEBUFFER:
                total_bootloader += entry->length;
                break;
            default:
                total_bootloader += entry->length;
                break;
        }
    }

    printk("[MEMMAP] ==================================================\n");
    printk("[MEMMAP] Summary:\n");
    printk("[MEMMAP]   Usable memory: %lu MiB\n", total_usable / (1024 * 1024));
    printk("[MEMMAP]   Reserved memory: %lu MiB\n", total_reserved / (1024 * 1024));
    printk("[MEMMAP]   Bootloader memory: %lu MiB\n", total_bootloader / (1024 * 1024));
    printk("[MEMMAP]   Total memory: %lu MiB\n",
              (total_usable + total_reserved + total_bootloader) / (1024 * 1024));

    printk("[MEMMAP] Note: per Limine base-revision-0 typical mapping: low 4GiB identity-mapped, + HHDM for high-half direct mapping.\n");
}



// 查找指定物理地址所在的内存区域
struct limine_memmap_entry* find_memmap_entry(uint64_t phys_addr) {
    struct limine_memmap_response *memmap = memmap_request.response;
    
    if (!memmap) {
        return NULL;
    }
    
    for (uint64_t i = 0; i < memmap->entry_count; i++) {
        struct limine_memmap_entry *entry = memmap->entries[i];
        if (phys_addr >= entry->base && phys_addr < entry->base + entry->length) {
            return entry;
        }
    }
    
    return NULL;
}

// 检查物理地址是否在可用内存中
bool is_phys_addr_usable(uint64_t phys_addr) {
    struct limine_memmap_entry *entry = find_memmap_entry(phys_addr);
    return entry && entry->type == LIMINE_MEMMAP_USABLE;
}

// 获取第一个可用内存区域的地址
uint64_t get_first_usable_addr(void) {
    struct limine_memmap_response *memmap = memmap_request.response;
    
    if (!memmap) {
        return 0;
    }
    
    for (uint64_t i = 0; i < memmap->entry_count; i++) {
        struct limine_memmap_entry *entry = memmap->entries[i];
        if (entry->type == LIMINE_MEMMAP_USABLE) {
            return entry->base;
        }
    }
    
    return 0;
}

// 获取最大的可用内存区域
struct limine_memmap_entry* get_largest_usable_region(void) {
    struct limine_memmap_response *memmap = memmap_request.response;
    
    if (!memmap) {
        return NULL;
    }
    
    struct limine_memmap_entry *largest = NULL;
    uint64_t max_size = 0;
    
    for (uint64_t i = 0; i < memmap->entry_count; i++) {
        struct limine_memmap_entry *entry = memmap->entries[i];
        if (entry->type == LIMINE_MEMMAP_USABLE && entry->length > max_size) {
            largest = entry;
            max_size = entry->length;
        }
    }
    
    return largest;
}
